package mp3;

 

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import main.MusicFile;
import net.sf.lamejb.impl.std.LameEncoderFactoryImpl;
import net.sf.lamejb.jna.std.LameErrorcodes;
import net.sf.lamejb.jna.std.MpegMode;
import net.sf.lamejb.jna.std.PaddingType;
import net.sf.lamejb.std.GenericEncoder;
import net.sf.lamejb.std.LameConfig;
import net.sf.lamejb.std.LameEncoderFactory;



public class MP3TOWAVCovertererImpl {
	
	public static void main(String[] args) throws Exception{
	   System.loadLibrary("libmp3lame");	
		MP3ConversionManager t = MP3ConversionManager.mp3ConversionManager;
	
		MP3TOWAVCovertererImpl co = new  MP3TOWAVCovertererImpl();
		
		co.MP3TOWAVCovertererInit("c:\\Users\\Jan\\a.wav", "c:\\Users\\Jan\\a.mp3");
		co.testOOPAPIGenericEncoder();
		
		 
	}
	ArrayList<MP3ConversionListenener> listeners = new ArrayList<MP3ConversionListenener>();
	
	GenericEncoder encoder;
	LameConfig conf;
	byte[] pWAVBuffer;
    byte[] pMP3Buffer;
    String mp3File;
    BufferedInputStream wavStream;
    BufferedOutputStream mp3Stream;
    private boolean isRunning = false;
    MusicFile m;
    
	public MP3TOWAVCovertererImpl(String wavFile,String mp3File,MusicFile m, MP3ConversionListenener listenener) throws IOException 
	
	{
		this.m = m;
		MP3TOWAVCovertererInit(wavFile, mp3File);
		listeners.add(listenener);
		
	}
	
	public MP3TOWAVCovertererImpl() {};
	
	public MP3TOWAVCovertererImpl(String wavFile,MusicFile m,String mp3File) throws IOException 
	
	{
		 
		this.m = m;
		MP3TOWAVCovertererInit(wavFile, mp3File);
 
	}
	
	public void MP3TOWAVCovertererInit(String wavFile,String mp3File) throws IOException {
 
	 new File(mp3File).delete();
	 
	 	LameEncoderFactory encoderFactory = new LameEncoderFactoryImpl();
	 	try {
        encoder = encoderFactory.createGenericEncoder();

	 	}
	 	catch (Exception e ) {
	 		e.printStackTrace();
	 	}
        conf = encoder.getLameConfig();
        conf.setErrorProtection(true);        
        conf.setNumChannels(2);
        
        conf.setMode(MpegMode.JOINT_STEREO);
        conf.setInSamplerate(48000);
        conf.setOutSamplerate(0);  // LAME selects    
        conf.setDisableReservoir(true);
        conf.setPaddingType(PaddingType.PAD_NO);
        conf.setBWriteVbrTag(true);
        conf.setBrate(320);
        conf.setQuality(10);
        conf.setOriginal(true);                      

        int[] pcmBufferSize = new int[1];
        int[] mp3BufferSize = new int[1];
        encoder.initEncoding(pcmBufferSize,mp3BufferSize);   

        int mBufferSize = pcmBufferSize[0];
        int mOutBufferSize = mp3BufferSize[0];
        
        // Allocate buffers
          pWAVBuffer = new byte[mBufferSize];
          pMP3Buffer = new byte[mOutBufferSize];            
        
        // WAV file supposed 44100 Hz, Stereo, 16 bits
         wavStream = new BufferedInputStream(new FileInputStream(wavFile));       
         mp3Stream = new BufferedOutputStream(new FileOutputStream(mp3File));
    
        wavStream.skip(44); // Skipping the WAV header        
        
	}
	
	
	public void start() {
		
		final MP3TOWAVCovertererImpl ref = this;
	 
				try {
					ref.testOOPAPIGenericEncoder();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		 
	}
	
    public void testOOPAPIGenericEncoder() throws Exception    
    {  
    
        
       
        
        // Convert All PCM samples
        int read;        
        double totalToTransfer = wavStream.available();
        
        
        while ( (read = wavStream.read(pWAVBuffer,0,pWAVBuffer.length)) > 0)
        {   
        	 
        	for(MP3ConversionListenener l :listeners) {
        		
        		l.transferred(m,(int)((totalToTransfer -wavStream.available() )*100/totalToTransfer));
        	}
 
            // Encode samples (read is "bytes")            
            int nOutputBytes = encoder.encodeBuffer(pWAVBuffer,read,pMP3Buffer);
            
             // write nOutputBytes bytes that are returned in the pMP3Buffer to disk
            mp3Stream.write(pMP3Buffer,0,nOutputBytes);
        }                
        
        int nOutputBytes = encoder.encodeFlush(pMP3Buffer);        
		// Are there any bytes pending? If so, write them to disk               
		if( nOutputBytes != 0 )
	            mp3Stream.write(pMP3Buffer,0,nOutputBytes);
       
        mp3Stream.flush();
        
        wavStream.close();
        mp3Stream.close();         

        encoder.writeVbrTag(mp3File);

        encoder.close();  
        
    	for(MP3ConversionListenener l :listeners) {
    		l.completed(m);
    	}
     }

    
    public static void checkError(int err)
    {
        if (err != LameErrorcodes.LAME_OKAY)
            throw new RuntimeException("ERROR " + err);     
    }

 
 
	
}
